package com.microservice.base.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.microservice.base.common.utils.ImageUtil;
import com.microservice.base.entity.*;
import com.microservice.base.mapper.hikcommon.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 调用海康接口的工具类
 *
 * @author jbx
 * @package_name com.microservice.base.common.utils
 * @create_date 2020/12/10 11:15
 */
@Component
@Transactional
public class HikInterfacePush {
  @Autowired
  OrgMP orgMP;
  @Autowired
  PersonMP personMP;
  @Autowired
  FaceMP faceMP;
  @Autowired
  CHkCameraMapper cameraMP;
  @Autowired
  CHkRegionMapper regionMP;
  Logger logger = LoggerFactory.getLogger(HikInterfacePush.class);
  SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
  // 调用组织的批量增加
  // 需要的数据是组织编号.组织名称,父组织结点
  // 单次提交的最大记录是1000条
  public void orgBatchAdd() {
    List<Org> orgs = orgMP.queryUpdate(2);
    Map<String, Object> maxLevels = orgMP.getMaxLevel();
    if (orgs.size() > 0) {
      Integer maxLevel = (Integer) maxLevels.get("maxLevel");
      List insertList = new ArrayList();
      for (int i = 1; i <= maxLevel; i++) {
        List<Org> orgs1 = orgMP.orgByLevelAndStatus(i, 0, 2);
        JSONArray jsonArray = new JSONArray();
        if (orgs1 != null && orgs1.size() > 0) {
          for (Org org : orgs1) {
            JSONObject jo = new JSONObject();
            jo.put("orgIndexCode", org.getOrgId());
            jo.put("orgName", org.getOrgName());
            jo.put("parentIndexCode", org.getParentOrgId());
            jsonArray.add(jo);
          }
          try {
            String s =
                HikConnection.pushHik("/api/resource/v1/org/batch/add", jsonArray.toString());
            logger.error("新增组织同步" + s);
            // 只有在同步成功过去之后,才进行org表状态的修改
            JSONObject jsonObject = JSONObject.parseObject(s);
            if ("success".equals(jsonObject.get("msg"))) {
              for (Org org : orgs1) {
                org.setOperation(0);
                insertList.add(org);
              }
            } else {
              logger.error("批量同步组织数据发生异常,请查看海康返回信息");
            }
          } catch (Exception e) {
            logger.error("连接海康服务器失败,组织数据批量新增失败");
          }
        }
      }
      if (insertList.size() > 0) {
        orgMP.replaceUpdate(insertList);
      }
      logger.error("成功.....新增海康数据库组织数据");
    } else {
      logger.error("没有需要批量新增的组织数据");
    }
  }
  // 调用组织的更新
  // 需要的参数:orgIndexCode->组织id,orgName->组织名称
  public void orgUpdate() {
    // 封装为json
    List<Org> orgsupdate = orgMP.queryUpdate(1);
    List<Org> orgsdelete = orgMP.queryDelete(1);
    // 获取全部的更新数据,要进行更新还是删除的判断
    if (orgsupdate.size() > 0) {
      List updateList = new ArrayList();
      for (Org org : orgsupdate) {
        // 修改只能单个修改
        JSONObject jo = new JSONObject();
        jo.put("orgIndexCode", org.getOrgId());
        jo.put("orgName", org.getOrgName());
        try {
          String s = HikConnection.pushHik("/api/resource/v1/org/single/update", jo.toString());
          logger.error("修改组织同步记录,组织id:" + org.getOrgId() + ";" + s);
          // 同步成功后更改org表的状态
          JSONObject jsonObject = JSONObject.parseObject(s);
          if ("success".equals(jsonObject.get("msg"))) {
            org.setOperation(0);
            updateList.add(org);
          } else {
            logger.error("修改组织数据失败,请查看海康返回数据");
          }
        } catch (Exception e) {
          logger.error("连接海康服务器失败,未能更新组织数据");
        }
      }
      if (updateList.size() > 0) {
        orgMP.replaceUpdate(updateList);
      }
      logger.error("成功.....更新海康数据库组织数据");
    } else {
      logger.error("没有需要更新的组织数据");
    }
    // 组织数据很少超过1000,故不做1000删除的限制
    // 删除是批量删除
    // 仅支持删除无子结点且组织下不存在人员的组织,故删除要从level从大到小删
    if (orgsdelete.size() > 0) {
      Map<String, Object> maxLevels = orgMP.getMaxLevel();
      Integer maxLevel = (Integer) maxLevels.get("maxLevel");
      for (int i = maxLevel; i > 0; i--) {
        JSONObject jo = new JSONObject();
        List<Org> orgByLevelAndStatus = orgMP.orgByLevelAndStatus(i, -1, 1);
        if (orgByLevelAndStatus.size() != 0) {
          String[] strings = new String[orgByLevelAndStatus.size()];
          for (int j = 0; j < orgByLevelAndStatus.size(); j++) {
            strings[j] = orgByLevelAndStatus.get(j).getOrgId();
          }
          jo.put("indexCodes", strings);
          try {
            String s = HikConnection.pushHik("/api/resource/v1/org/batch/delete", jo.toString());
            logger.error("删除组织同步记录" + s);
            JSONObject jsonObject = JSONObject.parseObject(s);
            if ("success".equals(jsonObject.get("msg"))) {
              for (Org org : orgByLevelAndStatus) {
                orgMP.updateOperation(0, org.getOrgId());
              }
            } else {
              logger.error("删除组织数据格式失败,请查看海康返回数据");
            }
          } catch (Exception e) {
            logger.error("连接海康服务器失败,未能删除组织数据");
          }
        }
      }
      logger.error("成功.....删除海康数据库组织数据");
    } else {
      logger.error("没有需要删除的组织数据");
    }
  }

  // ==========================================================================================
  // 人员的批量增加
  // 单次操作上限为1000条
  public void personBatchAdd() {
    // 先查询person表中新增人员信息
    List<Person> insertpeople = personMP.queryUpdate(2);
    if (insertpeople.size() > 0) {
      List insertList = new ArrayList();
      for (int i = 0; i <= insertpeople.size() / 1000; i++) {
        JSONArray jsonArray = new JSONArray();
        List<Person> people =
            insertpeople.stream().skip(i * 1000).limit(1000).collect(Collectors.toList());
        for (Person person : people) {
          JSONObject jo = new JSONObject();
          jo.put("personId", person.getPersonId());
          jo.put("personName", person.getPersonName());
          jo.put("gender", person.getSex());
          jo.put("orgIndexCode", person.getOrgId());
          jo.put("certificateType", person.getCertType() + "");
          jo.put("certificateNo", person.getCertNum());
          jo.put("jobNo", person.getEmployeeId());
          jsonArray.add(jo);
        }
        try {
          String s =
              HikConnection.pushHik("/api/resource/v1/person/batch/add", jsonArray.toString());
          logger.error("新增人员记录" + s);
          JSONObject jsonObject = JSONObject.parseObject(s);
          if ("success".equals(jsonObject.get("msg"))) {
            for (Person person : people) {
              person.setOperation(0);
              insertList.add(person);
            }
          } else {
            logger.error("新增人员数据发生异常,请查看海康返回数据");
          }
        } catch (Exception e) {
          logger.error("连接海康服务器失败,人员批量新增失败");
        }
      }

      // 新增完人员后,进行一卡通的新增
      // 查询有一卡通的有效信息,因为一旦重复会导致后面的数据无法导入,因此1条条的导入
      for (Person person : insertpeople) {
        JSONObject total = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        if ("0".equals(person.getCardStatus())) {
          JSONObject jo = new JSONObject();
          jo.put("cardNo", new BigInteger(person.getCardHex(), 16).toString());
          jo.put("personId", person.getPersonId());
          jo.put("orgIndexCode", person.getOrgId());
          jsonArray.add(jo);
        }
        if (jsonArray.size() > 0) {
          total.put("cardList", jsonArray);
          total.put("startDate", "2020-12-12");
          total.put("endDate", "2037-12-30");
          String s = HikConnection.pushHik("/api/cis/v1/card/bindings", total.toString());
          logger.error("新增人员卡片信息" + s);
        }
      }

      if (insertList.size() > 0) {
        personMP.replaceUpdate(insertList);
      }
      logger.error("成功.....新增海康人员数据");
    } else {
      logger.error("没有需要批量新增的人员数据");
    }
  }

  // 调用人员和卡片的更新
  public void PersonUpdate() {
    // 封装为json
    List<Person> peopleUpdate = personMP.queryUpdate(1);
    List<Person> peopleDelete = personMP.queryDelete(1);
    // 获取全部的更新数据,要进行更新还是删除的判断

    if (peopleUpdate.size() > 0) {
      // 修改是单个修改
      for (Person person : peopleUpdate) {
        JSONObject jo = new JSONObject();
        jo.put("personId", person.getPersonId());
        jo.put("personName", person.getPersonName());
        jo.put("gender", person.getSex());
        jo.put("orgIndexCode", person.getOrgId());
        jo.put("certificateType", person.getCertType() + "");
        jo.put("certificateNo", person.getCertNum());
        jo.put("jobNo", person.getEmployeeId());
        try {
          String s = HikConnection.pushHik("/api/resource/v1/person/single/update", jo.toString());
          logger.error("修改人员记录,人员id:" + person.getPersonId() + ";" + s);
          JSONObject jsonObject = JSONObject.parseObject(s);
          if ("success".equals(jsonObject.get("msg"))) {
            personMP.updateOperation(0, person.getPersonId());
          } else {
            logger.error("修改人员信息发生异常,请查看海康返回数据");
          }
        } catch (Exception e) {
          logger.error("连接海康服务器失败,人员更新失败");
        }
        try {
          if (person.getCardStatus() != null && !"0".equals(person.getCardStatus())) {
            // 删除卡片操作
            JSONObject deleteCard = new JSONObject();
            deleteCard.put("cardNumber", new BigInteger(person.getCardHex(), 16).toString());
            deleteCard.put("personId", person.getPersonId());
            String deleteCards =
                HikConnection.pushHik("/api/cis/v1/card/deletion", deleteCard.toString());
            logger.error("成功删除卡片信息:" + deleteCards);
          } else if ("0".equals(person.getCardStatus())) {
            JSONObject addCard = new JSONObject();
            JSONArray addCards = new JSONArray();
            JSONObject total = new JSONObject();
            addCard.put("cardNo", new BigInteger(person.getCardHex(), 16).toString());
            addCard.put("personId", person.getPersonId());
            addCard.put("orgIndexCode", person.getOrgId());
            addCards.add(addCard);
            total.put("cardList", addCards);
            total.put("startDate", "2020-12-12");
            total.put("endDate", "2037-12-30");
            String s = HikConnection.pushHik("/api/cis/v1/card/bindings", total.toString());
            logger.error("新增人员卡片信息" + s);
          }
        } catch (Exception e) {
          logger.error("更新卡片信息失败,错误信息:" + e);
        }
      }
      logger.error("成功......修改人员和卡片海康数据库");
    } else {
      logger.error("没有需要更新的人员数据");
    }

    // 批量删除
    if (peopleDelete.size() > 0) {
      for (int i = 0; i <= peopleDelete.size() / 1000; i++) {
        JSONObject jo = new JSONObject();
        String[] strings = new String[1000];
        List<Person> people =
            peopleDelete.stream().skip(i * 1000).limit(1000).collect(Collectors.toList());
        for (int j = 0; j < people.size(); j++) {
          strings[j] = peopleDelete.get(j).getOrgId();
        }
        jo.put("personIds", strings);
        try {
          String s = HikConnection.pushHik("/api/resource/v1/person/batch/delete", jo.toString());
          logger.error("删除人员记录" + s);
          JSONObject jsonObject = JSONObject.parseObject(s);
          if ("success".equals(jsonObject.get("msg"))) {
            for (Person person : people) {
              personMP.updateOperation(0, person.getPersonId());
            }
          } else {
            logger.error("删除人员信息出现异常,请查看海康返回数据");
          }
        } catch (Exception e) {
          logger.error("连接海康服务器失败,未能批量删除数据");
        }
      }
      logger.error("成功.....删除海康人员数据库");
    } else {
      logger.error("没有需要删除的人员数据");
    }
  }

  // ==============================================================================================
  // 调用人脸信息的单个增加
  // 新增的时候要注意,我们要获取海康返回的face_id存入到数据库中,以备后面的删除和修改使用
  public void faceAdd() {
    // 查询增加的人,增加是单个增加
    List<Face> faces = faceMP.queryUpdate(2);
    if (faces.size() > 0) {
      List<Face> updatefacelist = new ArrayList<>();
      for (Face value : faces) {
        JSONObject jo = new JSONObject();
        jo.put("personId", value.getPersonId());
        jo.put("faceData", ImageUtil.getImgUrlToBase64(value.getFaceUrl()));
        try {
          String s = HikConnection.pushHik("/api/resource/v1/face/single/add", jo.toString());
          logger.error("新增人脸记录,人脸人员id:" + value.getPersonId() + ";" + s);
          JSONObject jsonObject = JSONObject.parseObject(s);
          String faceid = (String) jsonObject.getJSONObject("data").get("faceId");
          // 新增数据时,要将海康生成的faceid存入数据库,后面的更新删除要用到
          if ("success".equals(jsonObject.getString("msg"))) {
            value.setFaceId(faceid);
            value.setOperation(0);
            updatefacelist.add(value);
          } else {
            logger.error("新增人脸数据失败,请查看海康返回数据");
          }
        } catch (Exception e) {
          logger.error("连接海康服务器失败,人脸新增失败");
        }
      }
      if (updatefacelist.size() > 0) {
        faceMP.replaceFaceid(updatefacelist);
      }
      logger.error("成功.....新增符合规范的人脸信息");
    } else {
      logger.error("无可新增的人脸数据");
    }
  }
  // 调用人脸的更新
  // 更新涉及修改和删除
  public void faceUpdate() {
    List<Face> facesUpdate = faceMP.queryUpdate(1);
    List<Face> facesDelete = faceMP.queryDelete(1);
    // 获取全部的更新数据,要进行更新还是删除的判断
    if (facesUpdate.size() > 0) {
      for (Face face : facesUpdate) {
        JSONObject jo = new JSONObject();
        jo.put("faceId", face.getFaceId());
        jo.put("faceData", ImageUtil.getImgUrlToBase64(face.getFaceUrl()));
        try {
          String s = HikConnection.pushHik("/api/resource/v1/face/single/update", jo.toString());
          logger.error("修改人脸记录,人脸人员id:" + face.getPersonId() + ";" + s);
          JSONObject jsonObject = JSONObject.parseObject(s);
          if ("success".equals(jsonObject.get("msg"))) {
            faceMP.updateOperation(0, face.getPersonId());
          } else {
            logger.error("修改人脸数据失败,清查看海康返回数据");
          }
        } catch (Exception e) {
          logger.error("连接海康服务器失败,人员更新失败");
        }
      }
      logger.error("成功.....修改符合规范的人脸信息");
    } else {
      logger.error("无需要更新的人员数据");
    }
    // 单个删除
    if (facesDelete.size() > 0) {
      for (Face face : facesDelete) {
        JSONObject jo = new JSONObject();
        String faceId = face.getFaceId();
        jo.put("faceId", faceId);
        try {
          String s =
              HikConnection.pushHik("/api/resource/v1/face/single/delete", jo.toJSONString());
          logger.error("删除人脸记录,人脸人员id:" + face.getPersonId() + ";" + s);
          JSONObject jsonObject = JSONObject.parseObject(s);
          if ("success".equals(jsonObject.get("msg"))) {
            faceMP.updateOperation(0, face.getPersonId());
          } else {
            logger.error("删除人脸数据失败,清查看海康返回数据");
          }
        } catch (Exception e) {
          logger.error("连接海康服务器失败,未能批量删除人脸数据");
        }
      }
      logger.error("成功.....删除符合规范的人脸信息");
    } else {
      logger.error("无需要删除的人脸数据");
    }
  }

  public void cameraAdd() {
    JSONObject jo = new JSONObject();
    jo.put("pageNo", "1");
    jo.put("pageSize", "1000");
    String s = HikConnection.pushHik("/api/resource/v2/camera/search", jo.toJSONString());
    JSONObject jsonObject = JSONObject.parseObject(s);
    JSONObject data = jsonObject.getJSONObject("data");
    if (data.getInteger("total") != 0) {
      List<CHkCamera> cameraList = data.getJSONArray("list").toJavaList(CHkCamera.class);
      // 获取cameraLists
      cameraMP.truncateTable();
      for (CHkCamera chkcamera : cameraList) {
        chkcamera.setDeleted("0");
        cameraMP.save(chkcamera);
      }
      logger.error("拉取成功所有监控信息" + cameraList);
    } else {
      logger.error("没有需要拉取的监控信息");
    }
  }

  public void regionAdd() {
    JSONObject jo = new JSONObject();
    jo.put("pageNo", "1");
    jo.put("pageSize", "1000");
    jo.put("resourceType", "region");
    String s = HikConnection.pushHik("/api/irds/v2/region/nodesByParams", jo.toJSONString());
    JSONObject jsonObject = JSONObject.parseObject(s);
    JSONObject data = jsonObject.getJSONObject("data");
    if (data.getInteger("total") != 0) {
      List<CHkRegion> regionList = data.getJSONArray("list").toJavaList(CHkRegion.class);
      regionMP.truncateTable();
      for (CHkRegion cHkRegion : regionList) {
        cHkRegion.setDeleted("0");
        regionMP.save(cHkRegion);
      }
      logger.error("拉取成功所有区域信息" + regionList);
    } else {
      logger.error("没有需要拉取的区域信息");
    }
  }
}
